/**
	Pulsar engine. Additional include file.
	Base application class.

	Copyright (C) 2013-2014 Dmitry Dolgov

	This program is free software; you can redistribute it and/or modify it under the terms of the
	GNU General Public License as published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.
*/

namespace pl
{

//
//Forward class declarations
//
class StartupFunc;
class CommandLine;
class CriticalSection;
struct ExceptionInfo;

template<pl_uint32 N> class String;
template<pl_uint32 N> class StringFormat;
typedef String<MAX_PATH> Filepath;

typedef String<32> String32;
typedef String<64> String64;
typedef String<128> String128;
typedef String<256> String256;

//
// Standard pathes (OS spec)
//
enum StarndardPath
{
	STANDARD_PATH_APPROOT,   // Path to executable file
	STANDARD_PATH_EXENAME,   // Executable file name (with full path)
	STANDARD_PATH_SYSTEM,    // System folder
	STANDARD_PATH_PROGRAMS,  // Program Files folder (Windows only)
	STANDARD_PATH_USERHOME,  // User's home folder
	STANDARD_PATH_DOCUMENTS, // User's 'My Documents' location (Windows only)
	STANDARD_PATH_SETTINGS,  // User's settings folder
	STANDARD_PATH_TEMP       // Temporary folder
};

/*
	Base application class
	User defined application should use platform specific declaration pl::App
*/
class AppBase
{
public:
	static AppBase* appBase;

#if defined(PL_ENTRY_POINT_INTERNAL)

protected:
	virtual void preInit(pl::StartupFunc& info) {}
	virtual int mainLoop() = 0;

#elif defined(PL_ENTRY_POINT_EXTERNAL)

public:
	virtual StartupFunc& getBaseSettings() = 0; // Can be used before init() only!!!
	virtual bool init(int argc, const pl_char* argv[]) = 0;
	virtual bool init(const pl_char* cmdLine) = 0;
	virtual void term() = 0;

#endif

public:
	/// Get command line
	inline const CommandLine* getCommandLine()
	{
		return _pCmdLine;
	}

	// Get standard path
	virtual const Filepath& getStdPath(StarndardPath path) = 0;

	// Get computer name
	virtual const String64& getComputerName() = 0;

	// Get current language
	virtual pl::String32 getCurrentLanguage() = 0;

	/// Get current date and time
	virtual bool getCurDateTime(DateTime& dateTime) = 0;

	virtual void terminateProcess(int exitCode) = 0;

	// Overrides in OS-specific (internal functions)
	virtual void _onTrace(const pl_char* file, pl_uint32 line, const pl_char* msg)
	{
		return;
	}
	virtual HandleResult _onAssert(const pl_char* file, pl_uint32 line, const pl_char* func, const pl_char* cond, const pl_char* msg, pl::AssertType type)
	{
		return HANDLE_RESULT_NEXT;
	}
	virtual HandleResult _onMemErr(const pl_char* file, pl_uint32 line, const pl_char* func, void* p, pl_int64 size, pl::MemoryError idEvent)
	{
		return HANDLE_RESULT_NEXT;
	}

protected:
	AppBase();
	virtual ~AppBase();

	void _initCore1();
	void _initCore2(pl::CommandLine* pCmdLine);
	void _termCore1();
	void _termCore2();

private:
	CommandLine* _pCmdLine;

};

/**
	Default settings for the initial setup
*/
class StartupFuncBase
{
public:
	/// Set global allocation hook
	void setGlobalAlloc(class IGlobalAlloc* iga);

	/// Set frame allocation options
	void setFrameAllocSize(pl_int32 size);

	/// Set stress memory manager options
	void memDebugSetStressAlloc(pl_uint32 nMaxBlocks, pl_uint32 nMaxSize);

	/// Set debug memory options
	void memDebugSetOptions(pl_uint32 options, pl_uint16 footerSize);

	/// Enable CPU affinity
	void setCpuAffinity(pl_uint32 indexMask);

	/// Setup maximum concurrent threads with logging (default: 20)
	void setMaxLogThreads(pl_uint32 nMaxThreads);

	/// Allow to trap signals from console application
	void enableSignals();

protected:
	StartupFuncBase() { }
};

} // namespace pl

//
// End of file 'pulsar_appbase.h'
//
